CloudFormation ForEach と FindInMap を使ってセキュリティグループを作ってみた
アノテーション 構築チームのいたくらです。
Fn::ForEach と Fn::FindInMap を使ってセキュリティグループを作ってみました。
Fn::ForEach で出来なかった部分が Fn::FindInMap で補えていい感じです。
Fn::ForEach や Fn::FindInMap について
とてもざっくりお伝えすると Fn::ForEach はループ処理のような機能を持つ関数で、
Fn::FindInMap は Mapping セクションで定義された値を取得する関数です。
詳細は公式ドキュメントを参照ください。
あと今回は shima さんのブログも参考にさせていただきました。
まえがき
shima さんのブログを拝見し、先日書いたこちらのブログのテンプレートを Fn::FindInMap で書き直せばいけそう!と思い、やってみたら成功しました!圧倒的感謝!
セキュリティグループを作成するテンプレート例
テンプレートが長いので閉じてあります。
以下のトグルを押すとテンプレートが開きます。
先日のブログで示したテンプレートから変更した部分をハイライトにしています。
CloudFormation テンプレート
AWSTemplateFormatVersion: "2010-09-09" Transform: 'AWS::LanguageExtensions' # ------------------------------------------------------------# # Parameters # ------------------------------------------------------------# Parameters: VpcId: Type: String Default: "vpc-xxxxxxxxxxxxxxxxx" # あらかじめ作成しておいた VPC ID SgList: Type: List<String> # ForEach で コレクションとして使用する値(Mappings の TopLevelKey と合わせる) Default: "SgIngress1,SgIngress2" # ------------------------------------------------------------# # Mappings # ------------------------------------------------------------# Mappings: SgMappings: SgIngress1: Cidr: "XX.XX.XX.XX/32" //自分の Global IP 等を適宜指定 FromPort: "80" ToPort: "80" SgIngress2: Cidr: "XX.XX.XX.XX/32" FromPort: "443" ToPort: "443" # ------------------------------------------------------------# # Resources # ------------------------------------------------------------# Resources: SecurityGroupAlb: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "Security Group for ALB" GroupName: "test-sg-alb" Tags: - Key: "Name" Value: "test-sg-alb" VpcId: !Ref VpcId 'Fn::ForEach::LoopIngress': # LoopPort の部分はテンプレート内で一意であること - SgIdentifier # ループ変数 - !Ref SgList # ループ変数で呼び出したい値(公式ドキュメントではコレクションと呼ぶ) - '${SgIdentifier}': # ループで作成されるリソースの論理 ID Type: AWS::EC2::SecurityGroupIngress Properties: CidrIp: !FindInMap - SgMappings # FindInMap の引数: MapName - !Ref SgIdentifier # FindInMap の引数: TopLevelKey - Cidr # FindInMap の引数: SecondLevelKey FromPort: !FindInMap - SgMappings - !Ref SgIdentifier - FromPort ToPort: !FindInMap - SgMappings - !Ref SgIdentifier - ToPort IpProtocol: "TCP" GroupId: !Ref SecurityGroupAlb
このテンプレートで作成できたセキュリティグループがこちら。
先日のブログと違って、HTTP と HTTPS のインバウンドルールが設定できています。
疑問:複数回呼び出しできないんじゃなかったのか?
先日書いたブログのここを見ていただくと分かるように、ループ変数を複数回参照したらエラーが出ました。
でも今回のテンプレートで複数回参照しても問題なく成功したのはなぜなのでしょう。
Fn::FindInMap の引数としてループ変数が参照されているだけで、実際にオブジェクトで参照しているのは Mappings で定義した値。
ループ変数をオブジェクトで直接参照できるのは 1 回のみだけど、引数として参照するなら複数回可能、って感じなんでしょうか。
難しいですね・・・
あとがき
先日のブログで「Fn::ForEach はセキュリティグループに向いてないかもしれません」と書いてましたが、「Fn::ForEach だけだと、」に修正しました(笑)
CloudFormation 歴が浅いため、恥ずかしながら後からこんなこともできるのか!と知ることが多く、とても勉強になりました。
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。
「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。
現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。